package top.as.sean.biz.system.impl;

import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import top.as.sean.biz.system.IDept;
import top.as.sean.common.constant.Constant;
import top.as.sean.common.exception.GlobalException;
import top.as.sean.common.guava.GuavaCache;
import top.as.sean.common.id.SnowflakeId;
import top.as.sean.common.response.RespStatus;
import top.as.sean.common.tree.TreeUtil;
import top.as.sean.dao.dto.system.DeptAdd;
import top.as.sean.dao.dto.system.DeptEdit;
import top.as.sean.dao.dto.system.DeptPage;
import top.as.sean.dao.entity.pojo.system.Dept;
import top.as.sean.dao.mapper.system.DeptMapper;
import top.as.sean.dao.vo.system.DeptTree;
import top.as.sean.dao.vo.system.DeptTreeVo;

import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
 * 部门
 *
 * @author: ArchieSean
 * @create: 2022/11/8
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DeptImpl extends ServiceImpl<DeptMapper, Dept> implements IDept {
    /**
     * 翻译核心
     */
    private final GuavaCache guavaCache;

    /**
     * 删除、逻辑删除
     *
     * @param id id
     * @return boolean
     */
    @Override
    public Boolean removeOne(Long id) {
        List<Dept> depts = this.lambdaQuery().eq(Dept::getId, id).or().eq(Dept::getParentId, id).list();
        if (CollectionUtils.isEmpty(depts)) {
            throw new GlobalException(RespStatus.DEPT_NOT_FOUND);
        }
        List<Dept> updates = Lists.newArrayList();
        depts.forEach(dept -> {
            Dept updateDept = new Dept();
            updateDept.setId(dept.getId());
            updateDept.setDelFlag(Constant.CommonDelete.DELETE.getCode());
            updates.add(updateDept);
        });
        return updateBatchById(updates);
    }

    /**
     * 编辑部门信息
     *
     * @param dto 入参
     * @return boolean
     */
    @Override
    public Boolean editDept(DeptEdit dto) {
        //父节点不能是自己
        if (ObjUtil.isNotEmpty(dto.getParentId()) && dto.getId().equals(dto.getParentId())) {
            throw new GlobalException(RespStatus.DEPT_NOT);
        }
        Dept dept = this.lambdaQuery().eq(Dept::getId, dto.getId()).one();
        if (ObjUtil.isEmpty(dept)) {
            throw new GlobalException(RespStatus.DEPT_NOT_FOUND);
        }
        if (StringUtils.hasLength(dto.getDeptName()) && !dto.getDeptName().equals(dept.getDeptName())
                && validateDeptName(dto.getDeptName())) {
            throw new GlobalException(RespStatus.DEPT_NAME_EXIST);
        }
        Dept updateDept = new Dept();
        BeanUtils.copyProperties(dto, updateDept);
        return updateById(updateDept);
    }

    /**
     * 新增部门信息
     *
     * @param dto 入参
     * @return boolean
     */
    @Override
    public Boolean addDept(DeptAdd dto) {
        if (validateDeptName(dto.getDeptName())) {
            throw new GlobalException(RespStatus.DEPT_NAME_EXIST);
        }
        Dept insertDept = new Dept();
        BeanUtils.copyProperties(dto, insertDept);
        insertDept.setId(SnowflakeId.createId());
        return save(insertDept);
    }

    /**
     * 用于校验部门-名称是否可用
     *
     * @param deptName 部门名称
     * @return boolean
     */
    private Boolean validateDeptName(String deptName) {
        return this.lambdaQuery().eq(Dept::getDeptName, deptName).exists();
    }

    /**
     * 查询部门树形
     *
     * @param dto 入参
     * @return list
     */
    @Override
    public List<DeptTree> getTree(DeptPage dto) {
        List<Dept> list = this.lambdaQuery()
                .like(StringUtils.hasLength(dto.getDeptName()), Dept::getDeptName, dto.getDeptName())
                .eq(StringUtils.hasLength(dto.getStatus()), Dept::getStatus, dto.getStatus())
                .eq(Dept::getDelFlag, Constant.CommonDelete.ENABLE.getCode())
                .list();
        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }
        List<DeptTree> result = Lists.newArrayList();
        list.forEach(dept -> {
            DeptTree deptTree = new DeptTree();
            BeanUtils.copyProperties(dept, deptTree);
            deptTree.setStatusDict(deptTree.getStatus());
            result.add(deptTree);
        });
        //翻译
        try {
            guavaCache.translateList(result);
        } catch (Exception e) {
            log.error("手动翻译部门数据异常--->", e);
        }
        //根据排序字段倒叙
        return TreeUtil.build(result, 0L, Comparator.comparing(DeptTree::getOrderNum));
    }

    /**
     * 根据部门ids查询部门信息
     *
     * @param deptIds 部门ids
     * @return list
     */
    @Override
    public List<Dept> findByIds(Set<Long> deptIds) {
        return this.lambdaQuery().in(!CollectionUtils.isEmpty(deptIds), Dept::getId, deptIds)
                .eq(Dept::getDelFlag, Constant.CommonDelete.ENABLE.getCode())
                .eq(Dept::getStatus, Constant.CommonStatus.ENABLE.getCode())
                .list();
    }

    /**
     * 查询所有可用部门
     *
     * @return list
     */
    @Override
    public List<DeptTreeVo> getAll() {
        List<Dept> list = findByIds(null);
        List<DeptTreeVo> result = Lists.newArrayList();
        list.forEach(dept -> {
            DeptTreeVo vo = new DeptTreeVo();
            BeanUtils.copyProperties(dept, vo);
            result.add(vo);
        });
        return TreeUtil.build(result, BigDecimal.ZERO.longValue(), Comparator.comparing(DeptTreeVo::getId));
    }
}
